#if USE_BESTHTTP
using BestHTTP.Connections;
#endif
using NL;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace SinceTimes.NetWork
{
    public enum ConnectionModel
    {
        TCP = 0,
        UDP = 1,
        WebSocket = 11,
        HTTPWebSocket=22,
        NativeWebSocket=33,
    }
    [Serializable]
    public struct ConnectionRuntime
    {
        public string State;

        public bool Receiving;

        public int  SendAll;
        public float LastSended;

        public int ReceiveAll;
        public float LastReceived;

        public override string ToString()
        {
            return $"[{State}]: Send:{ SendAll} \t Receive:{ReceiveAll}  ";
        }
    }

    public delegate string StringAction<T0,T1,T2,T3>(T0 arg0,T1 arg1, T2 arg2,T3 arg3);
    [System.Serializable]
    public class Connection  
    {


        public string Url;
        public int Port;

        public ConnectionRuntime RuntimeState;

        public bool Logable=true;
        public virtual string State { get; }
        public string Error;

        public virtual bool Connected { get; }

        //public IDataPackage DataPackager { get; set; }

        // 各类回调 接口
        public Action<Connection> OnConnectedCallBack, OnClosedCallBack;
        public Action<byte[], uint, uint> OnReceivedCallBack;

        public StringAction<Connection,byte[],uint, uint> OnUserAuth;

        public bool UserAuthCheckable = true;

        public virtual float Latency { get;  } =0;

        public const uint BUFF_MAX = 65535;

        protected MonoBehaviour Owner;
        public Connection(MonoBehaviour owner)
        {
            Owner = owner;
        }

        //protected virtual IDataPackage _DoInitDataPacker()
        //{
        //    return null;
        //}


        //
        /// <summary>
        /// 链接 建立..........
        /// </summary>
        /// <returns></returns>
        public Connection Connect()
        {
            _DoConnect();
            return this;
        }
        protected virtual void _DoConnect()
        {
            Connecting=true;
        }
        protected virtual void OnConnectSuccess()
        {
            ConnectOK = true;
            Connecting = false;

            if (Net.SHOWLOG) Debug.Log($"[Net.Connection._OnConnect]:{Error}");
            OnConnectedCallBack?.Invoke(this);
        }
        protected   bool ConnectOK = false;

        protected virtual void OnConnectError(string e)
        {
            Connecting = false;
        }
        public bool Connecting = false;
        // 等待到 链接完成...
        public WaitUntil UntilConnectOver() => new WaitUntil(() => !Connecting);

        protected virtual void  _DoError(string err)
        {
            Error = err;

            //是建立链接的时候出错了吗..
            if (Connecting)
            {
                OnConnectError(err);
            }
        }


        /// <summary>
        /// 关闭 .......................
        /// </summary>
        /// <returns></returns>
        public Connection Close(bool callback=false)
        {
            _DoClose(callback);
            return this;
        }

        protected virtual void _DoClose(bool callback = false)
        {
            if (Connecting) Connecting = false;


            _OnClose();

            if(callback)
                OnClosedCallBack?.Invoke(this);
        }
        protected virtual void _OnClose()
        {
            ConnectOK = false;
            if(Net.SHOWLOG)Debug.Log($"[Net.Connection._OnClose]:{Error}");

        }

        public  int Send(byte[] data)
        {
            
            return _DoSend(data);
        }


        protected virtual int  _DoSend(byte[] data)
        {
            return 0;
        }

        protected virtual void _OnSend(byte[] data)
        {
            if( Net.SHOWLOG) 
                Debug.Log($"[Net.Connection._OnSend]:count{data.Length} ; buff:{Net.BYTES_STRING(data, 0, data.Length)}");
            RuntimeState.SendAll++;
            RuntimeState.LastSended = Time.realtimeSinceStartup;
        }



        protected virtual void _OnReceive(byte[] buff, uint offset, uint len)
        {
            if ( Net.SHOWLOG)
                Debug.Log($"[Net.Connection._OnReceive]:count{len} ; buff:{Net.BYTES_STRING(buff, 0, (int)len)}");

            RuntimeState.ReceiveAll++;
            RuntimeState.LastReceived = Time.realtimeSinceStartup;

            OnReceivedCallBack?.Invoke(buff, offset, len);
        }

        //protected    Action<string> _ONConnect;
        //public PeerConnection WaitConnect(Action<string> callback)
        //{
        //    _ONConnect = callback;return this;
        //}

        //protected Action<string> _ONClose;
        //public PeerConnection WaitClose(Action<string> callback)
        //{
        //    _ONClose = callback; return this;
        //}

        //protected Action<byte[],uint, uint> _ONReceive;
        //public PeerConnection WaitRecive(Action<byte[],uint, uint> callback)
        //{
        //    _ONReceive=callback;return this;
        //}

        protected byte[] _Buff_Authenticate;
        public Connection UseAuthenticate(byte[] buff)
        {
            _Buff_Authenticate = buff; return this;
        }


        protected virtual void RuntimeCheck()
        {

        }

        public virtual void Loop()
        {
            RuntimeCheck();
        }
    }
}

